New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add plugin infra for adding new dashboard tabs/cards #1742
Add plugin infra for adding new dashboard tabs/cards #1742
Conversation
Hi @rawagner. Thanks for your PR. I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/approve |
/ok-to-test |
41bceca
to
723918a
Compare
After discussion with @vojtechszocs I changed this a bit - adding tabs and cards is a separate extension. I also improved types a bit. |
position: GridPosition; | ||
|
||
/** The card component to render */ | ||
component: React.ComponentType<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Directly referencing a React component from within a plugin's entry module will make it part of the Console initial chunk, which is already too big.
The default strategy for referencing plugin-contributed React components should be
Promise<TypeOfComponent>
and using either
() => import('./path/to/module' /* webpackChunkName: "chunk-name" */).then(m => m.MyComponent)
or
async () => (await import('./path/to/module' /* webpackChunkName: "chunk-name" */)).MyComponent
to provide those components.
Please add the following into typings/index.ts
:
type LazyLoader<T> = () => Promise<React.ComponentType<T>>;
and use it in both typings/pages.ts
and typings/dashboards.ts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cant move LazyLoader
type to typings/index.ts
because that results in a circular dependency. Moved it to typings/types.ts
.
@@ -98,7 +98,7 @@ const AppContents = withRouter(React.memo(() => ( | |||
|
|||
<Route path={['/all-namespaces', '/ns/:ns']} component={RedirectComponent} /> | |||
|
|||
<LazyRoute path="/dashboards" exact loader={() => import('./dashboards-page/dashboards' /* webpackChunkName: "dashboards" */).then(m => m.DashboardsPage)} /> | |||
<LazyRoute path="/dashboards" loader={() => import('./dashboards-page/dashboards' /* webpackChunkName: "dashboards" */).then(m => m.DashboardsPage)} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI @spadgett plugins can add new tabs into existing Dashboards page, with tab ID reflected into the URL.
{ | ||
href: '', | ||
name: 'Overview', | ||
component: OverviewDashboard, | ||
}, | ||
]; | ||
|
||
const getCardsOnPosition = (cards: DashboardsCard[], position: GridPosition): React.ComponentType<any>[] => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To render lazy (async) components, you can use Promise-based AsyncComponent
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using AsyncComponent
now
My only concern here is to ensure that we load custom components lazily instead of referencing them directly, please see my inline comments for details. |
723918a
to
ef90913
Compare
Thanks @vojtechszocs for review. I addressed all issues, can you take a look again ? |
return plugins.registry.getDashboardsTabs().map(tab => { | ||
const tabCards = cards.filter(c => c.properties.tab === tab.properties.id); | ||
return { | ||
href: tab.properties.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also write an extension check that ensures tab IDs are unique (and non-empty as well), I'll put it on my task list.
In general, every time we add new extension types, we should also consider writing the corresponding extension checks to guard against potential conflicts.
aa9507b
to
e29751c
Compare
@spadgett can you take a look ? |
@cloudbehl you should not really be blocked, the API should not change so it is safe to base your work on this already |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: rawagner, spadgett, vojtechszocs The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest |
@vojtechszocs @cloudbehl